home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 15 / CU Amiga Magazine's Super CD-ROM 15 (1997)(EMAP Images)(GB)[!][issue 1997-10].iso / CUCD / Graphics / Ghostscript / source / gdevsj48.c < prev    next >
Text File  |  1994-09-21  |  9KB  |  294 lines

  1. /* Copyright (C) 1990, 1992, 1993 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of Aladdin Ghostscript.
  4.   
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.   
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19. /*
  20.  * gdevsj48.c --- derived from gdevbj10.c 1993-10-07
  21.  *                by Mats kerblom (f86ma@dd.chalmers.se).
  22.  * 
  23.  *
  24.  * StarJet SJ48 printer driver.
  25.  *
  26.  */
  27.  
  28. #include "gdevprn.h"
  29.  
  30.  
  31. /*
  32.  * The only available resolutions (in the program) are (180,360)x(180,360).
  33.  *
  34.  * Used control codes:
  35.  *   <Esc>@    Printer reset
  36.  *   <Esc>J<n>    Make a n/180 inch linefeed
  37.  *   <Esc>\<a><b>    Move the print position (a+256b)/180 inch to the right
  38.  *   <Esc>*<m><a><b>... Print graphics; m=39: 180*180 dpi
  39.  *                    m=40: 360*180 dpi
  40.  *                    m=71: 180*360 dpi
  41.  *                    m=72: 360*360 dpi
  42.  *            a+256b columns is printed.
  43.  */
  44.  
  45. /* The device descriptor */
  46. private dev_proc_print_page(sj48_print_page);
  47. gx_device_printer far_data gs_sj48_device =
  48.   prn_device(prn_std_procs, "sj48",
  49.     80,                /* width_10ths, 8" */
  50.     105,                /* height_10ths, 10.5" */
  51.     360,                /* x_dpi */
  52.     360,                /* y_dpi */
  53.     0,0,0,0,            /* margins */
  54.     1, sj48_print_page);
  55.  
  56.  
  57. /*   This comes from the bj10/bj200 source. I don't know how it applies
  58.  *   for a StarJet.  --- Mats kerblom.
  59.  *
  60.  *
  61.  * The following is taken from the BJ200 Programmer's manual.  The top
  62.  * margin is 3mm (0.12"), and the bottom margin is 6.4mm (0.25").  The
  63.  * left and right margin depend on the type of paper -- US letter or
  64.  * A4 -- but ultimately rest on a print width of 203.2mm (8").  For letter
  65.  * paper, the left margin (and hence the right) is 6.4mm (0.25"), while
  66.  * for A4 paper, both are 3.4mm (0.13").
  67.  *
  68.  * The bottom margin requires a bit of care.  The image is printed
  69.  * as strips, each about 3.4mm wide.  We can only attain the bottom 
  70.  * margin if the final strip coincides with it.  Note that each strip
  71.  * is generated using only 48 of the available 64 jets, and the absence
  72.  * of those bottom 16 jets makes our bottom margin, in effect, about
  73.  * 1.1mm (0.04") larger.
  74.  *
  75.  * The bj200 behaves, in effect, as though the origin were at the first
  76.  * printable position, rather than the top left corner of the page, so
  77.  * we add a translation to the initial matrix to compensate for this.
  78.  *
  79.  * Except for the details of getting the margins correct, the bj200 is
  80.  * no different from the bj10e, and uses the same routine to print each
  81.  * page.
  82.  *
  83.  */
  84.  
  85.  
  86. /* Send the page to the printer. */
  87. private int
  88. sj48_print_page(gx_device_printer *pdev, FILE *prn_stream)
  89. {    int line_size = gx_device_raster((gx_device *)pdev, 0);
  90.     int xres = pdev->x_pixels_per_inch;
  91.     int yres = pdev->y_pixels_per_inch;
  92.     int mode = (yres == 180 ?
  93.             (xres == 180 ? 39 : 40) :
  94.             (xres == 180 ? 71 : 72));
  95.     int bytes_per_column = (yres == 180) ? 3 : 6;
  96.     int bits_per_column = bytes_per_column * 8;
  97.     int skip_unit = bytes_per_column * (xres == 180 ? 1 : 2); /* Skips in step of 1/180" */
  98.     byte *in = (byte *)gs_malloc(8, line_size, "sj48_print_page(in)");
  99.     byte *out = (byte *)gs_malloc(bits_per_column, line_size, "sj48_print_page(out)");
  100.     int lnum = 0;
  101.     int skip = 0;
  102.     int skips;
  103.     int code = 0;
  104.     int last_row = dev_print_scan_lines(pdev);
  105.     int limit = last_row - bits_per_column;
  106.  
  107.     if ( in == 0 || out == 0 )
  108.     {    code = gs_error_VMerror;
  109.         gs_note_error(code);
  110.         goto fin;
  111.     }
  112.  
  113.     /* Abort if the requested resolution is unsupported. */
  114.     if ((xres !=180 && xres != 360) || (yres !=180 && yres != 360))
  115.     {    code = gs_error_rangecheck;
  116.         gs_note_error(code);
  117.         goto fin;
  118.     }
  119.  
  120.     /* Initialize the printer. */
  121.     fwrite("\033@\000\000", 1, 4, prn_stream);  /* <Printer reset>, <0>, <0>. */
  122.  
  123.     /* Transfer pixels to printer.  The last row we can print is defined
  124.        by "last_row".  Only the bottom of the print head can print at the
  125.        bottom margin, and so we align the final printing pass.  The print
  126.        head is kept from moving below "limit", which is exactly one pass
  127.        above the bottom margin.  Once it reaches this limit, we make our
  128.        final printing pass of a full "bits_per_column" rows. */
  129.     while ( lnum < last_row )
  130.        {    
  131.         byte *in_data;
  132.         byte *in_end = in + line_size;
  133.         byte *out_beg = out;
  134.         byte *out_end = out + bytes_per_column * pdev->width;
  135.         byte *outl = out;
  136.         int count, bnum;
  137.  
  138.         /* Copy 1 scan line and test for all zero. */
  139.         code = gdev_prn_get_bits(pdev, lnum, in, &in_data);
  140.         if ( code < 0 ) goto xit;
  141.         /* The mem... or str... functions should be faster than */
  142.         /* the following code, but all systems seem to implement */
  143.         /* them so badly that this code is faster. */
  144.            {    register const long *zip = (const long *)in_data;
  145.             register int zcnt = line_size;
  146.             register const byte *zipb;
  147.             for ( ; zcnt >= 4 * sizeof(long); zip += 4, zcnt -= 4 * sizeof(long) )
  148.                {    if ( zip[0] | zip[1] | zip[2] | zip[3] )
  149.                     goto notz;
  150.                }
  151.             zipb = (const byte *)zip;
  152.             while ( --zcnt >= 0 )
  153.                {
  154.                 if ( *zipb++ )
  155.                     goto notz;
  156.                }
  157.             /* Line is all zero, skip */
  158.             lnum++;
  159.             skip++;
  160.             continue;
  161. notz:            ;
  162.            }
  163.  
  164.         /* Vertical tab to the appropriate position.  Note here that
  165.            we make sure we don't move below limit. */
  166.         if ( lnum > limit )
  167.             {    skip -= (limit - lnum);
  168.             lnum = limit;
  169.             }
  170.  
  171.         /* The SJ48 can only skip in steps of 1/180" */
  172.         if (yres == 180) {
  173.           skips = skip;
  174.         } else {
  175.           if (skip & 1) {
  176.             skip--; /* Makes skip even. */
  177.             lnum--;
  178.           }
  179.                   skips = skip/2;
  180.         } 
  181.             
  182.         while ( skips > 255 )
  183.            {    fputs("\033J\377", prn_stream);
  184.             skips -= 255;
  185.            }
  186.         if ( skips )
  187.             fprintf(prn_stream, "\033J%c", skips);
  188.  
  189.         /* If we've printed as far as "limit", then reset "limit"
  190.            to "last_row" for the final printing pass. */
  191.         if ( lnum == limit )
  192.             limit = last_row;
  193.         skip = 0;
  194.  
  195.         /* Transpose in blocks of 8 scan lines. */
  196.         for ( bnum = 0; bnum < bits_per_column; bnum += 8 )
  197.            {    int lcnt = min(8, limit - lnum);
  198.             byte *inp = in;
  199.             byte *outp = outl;
  200.                lcnt = gdev_prn_copy_scan_lines(pdev,
  201.                 lnum, in, lcnt * line_size);
  202.             if ( lcnt < 0 )
  203.                {    code = lcnt;
  204.                 goto xit;
  205.                }
  206.             if ( lcnt < 8 )
  207.                 memset(in + lcnt * line_size, 0,
  208.                        (8 - lcnt) * line_size);
  209.             for ( ; inp < in_end; inp++, outp += bits_per_column )
  210.                {    gdev_prn_transpose_8x8(inp, line_size,
  211.                     outp, bytes_per_column);
  212.                }
  213.             outl++;
  214.             lnum += lcnt;
  215.             skip += lcnt;
  216.            }
  217.  
  218.         /* Send the bits to the printer.  We alternate horizontal
  219.            skips with the data.  The horizontal skips are in units
  220.            of 1/180 inches, so we look at the data in groups of
  221.            1 or 2 columns depending on resolution (controlled
  222.                    by skip_unit).  */
  223.         outl = out;
  224.         do
  225.            {    int count;
  226.             int n;
  227.             byte *out_ptr;
  228.  
  229.             /* First look for blank groups of columns. */
  230.             while(outl < out_end)
  231.                {    n = count = min(out_end - outl, skip_unit);
  232.                 out_ptr = outl;
  233.                 while ( --count >= 0 )
  234.                    {    if ( *out_ptr++ )
  235.                         break;
  236.                    }
  237.                 if ( count >= 0 )
  238.                     break;
  239.                 else
  240.                     outl = out_ptr;
  241.                }
  242.             if (outl >= out_end)
  243.                 break;
  244.             if (outl > out_beg)
  245.                {    count = (outl - out_beg) / skip_unit;
  246.                 fprintf(prn_stream, "\033\\%c%c",
  247.                     count & 0xff, count >> 8);
  248.                }
  249.  
  250.             /* Next look for non-blank groups of columns. */
  251.             out_beg = outl;
  252.             outl += n;
  253.             while(outl < out_end)
  254.                {    n = count = min(out_end - outl, skip_unit);
  255.                 out_ptr = outl;
  256.                 while ( --count >= 0 )
  257.                    {    if ( *out_ptr++ )
  258.                         break;
  259.                    }
  260.                 if ( count < 0 )
  261.                     break;
  262.                 else
  263.                     outl += n;
  264.                }
  265.             count = outl - out_beg;
  266.             {
  267.               /* What to transmit is the number of columns in the row.
  268.                  Compare this with the <Esc>|*-command wich expects the
  269.                  total number of bytes in the graphic row! */
  270.               int count1 = count/bytes_per_column;
  271.               fprintf(prn_stream, "\033*%c%c%c",
  272.                   mode, count1 & 0xff, count1 >> 8);
  273.             }
  274.             fwrite(out_beg, 1, count, prn_stream);
  275.             out_beg = outl;
  276.             outl += n;
  277.            }
  278.         while ( out_beg < out_end );
  279.  
  280.         fputc('\r', prn_stream);
  281.         skip = bits_per_column;  /* <CR> only moves to the beginning of the row. */
  282.        }
  283.  
  284.     /* Eject the page */
  285. xit:    fputc(014, prn_stream);    /* form feed */
  286.     fflush(prn_stream);
  287. fin:    if ( out != 0 )
  288.         gs_free((char *)out, bits_per_column, line_size,
  289.             "sj48_print_page(out)");
  290.     if ( in != 0 )
  291.         gs_free((char *)in, 8, line_size, "sj48_print_page(in)");
  292.     return code;
  293. }
  294.